package cn.edu.neu.vmmigeval.cloud.entity;

import cn.edu.neu.vmmigeval.cloud.policy.VmScheduler;
import cn.edu.neu.vmmigeval.evaluation.PowerModel;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by yfwz100 on 16/2/25.
 */
public class Host {

    /** The id. */
    private int id;

    /** The allocation policy. */
    private VmScheduler vmScheduler;
    /** The vm list. */
    private final List<Vm> vmList = new ArrayList<Vm>();

    /** The pe list. */
    private List<PE> peList;

    /** The vms migrating in. */
    private final List<Vm> vmsMigratingIn = new ArrayList<Vm>();

    /** The vms migrating out. */
    private final List<Vm> vmsMigratingOut = new ArrayList<Vm>();

    /**
     * 当前使用的Cpu
     */
    private int currentCpu;
    /**
     * 当前host上总的Cpu
     */
    private int totalCpu;
    /**
     * 当前使用的Ram
     */
    private int currentRam;
    /**
     * 当前host上总的Ram
     */
    private int totalRam;
    /**
     * 当前使用的Bw
     */
    private int currentBw;
    /**
     * 当前host上总的Bw
     */
    private int totalBw;
    /**
     * 当前使用的Disk
     */
    private int currentDisk;
    /**
     * 当前host上总的Disk
     */
    private int totalDisk;

    /**
     * 状态   0:active 1:shutdown
     */
    private int active;

    /**
     * 迁移
     */
    private boolean isMigration;

    /**
     * 0
     * 1  int
     * 2  out
     */
    private int migrationIn;

    /**
     * 排序因子
     */
    private double sortingFactor;

    private List<Double> utilizationHistory =new ArrayList<Double>();


    private double additionalPower;

    private double score;
    //	0 表示高负载  		1 表示低负载
    private int loadFlag=0;

    public Host(){

    }

    public Host(int id,List<PE> peList, int totalCpu, int totalRam, int totalBw,
                int totalDisk,VmScheduler vmScheduler) {
        super();
        this.id = id;
        this.peList = peList;
        this.totalCpu = totalCpu;
        this.totalRam = totalRam;
        this.totalBw = totalBw;
        this.totalDisk = totalDisk;
        this.vmScheduler = vmScheduler;
    }

    public Host(int id, VmScheduler vmScheduler, List<PE> peList,
                int currentCpu, int totalCpu, int currentRam, int totalRam,
                int currentBw, int totalBw, int currentDisk, int totalDisk,
                int active) {
        super();
        this.id = id;
        this.vmScheduler = vmScheduler;
        this.peList = peList;
        this.currentCpu = currentCpu;
        this.totalCpu = totalCpu;
        this.currentRam = currentRam;
        this.totalRam = totalRam;
        this.currentBw = currentBw;
        this.totalBw = totalBw;
        this.currentDisk = currentDisk;
        this.totalDisk = totalDisk;
        this.active = active;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public VmScheduler getVmScheduler() {
        return vmScheduler;
    }

    public void setVmScheduler(VmScheduler vmScheduler) {
        this.vmScheduler = vmScheduler;
    }

    public List<PE> getPeList() {
        return peList;
    }

    public void setPeList(List<PE> peList) {
        this.peList = peList;
    }

    public int getCurrentCpu() {
        return currentCpu;
    }

    public void setCurrentCpu(int currentCpu) {
        this.currentCpu = currentCpu;
    }

    public int getTotalCpu() {
        return totalCpu;
    }

    public void setTotalCpu(int totalCpu) {
        this.totalCpu = totalCpu;
    }

    public int getCurrentRam() {
        return currentRam;
    }

    public void setCurrentRam(int currentRam) {
        this.currentRam = currentRam;
    }

    public int getTotalRam() {
        return totalRam;
    }

    public void setTotalRam(int totalRam) {
        this.totalRam = totalRam;
    }

    public int getCurrentBw() {
        return currentBw;
    }

    public void setCurrentBw(int currentBw) {
        this.currentBw = currentBw;
    }

    public int getTotalBw() {
        return totalBw;
    }

    public void setTotalBw(int totalBw) {
        this.totalBw = totalBw;
    }

    public int getCurrentDisk() {
        return currentDisk;
    }

    public void setCurrentDisk(int currentDisk) {
        this.currentDisk = currentDisk;
    }

    public int getTotalDisk() {
        return totalDisk;
    }

    public void setTotalDisk(int totalDisk) {
        this.totalDisk = totalDisk;
    }

    public int getActive() {
        return active;
    }

    public void setActive(int active) {
        this.active = active;
    }

    public List<Vm> getVmList() {
        return vmList;
    }

    public List<Vm> getVmsMigratingIn() {
        return vmsMigratingIn;
    }

    public List<Vm> getVmsMigratingOut() {
        return vmsMigratingOut;
    }

    public boolean isMigration() {
        return isMigration;
    }

    public void setMigration(boolean isMigration) {
        this.isMigration = isMigration;
    }


    public double getSortingFactor() {
        return sortingFactor;
    }

    public void setSortingFactor(double sortingFactor) {
        this.sortingFactor = sortingFactor;
    }

    public boolean isSuitableForVm(Vm vm) {
        if(this.vmList == null /*|| this.vmList.size()==0*/){
            return false;
        }else{
            int cpu = 0,ram = 0 ,bw=0,disk=0;
            for (Vm vm2 : vmList) {
                cpu+=vm2.getTotalCpu();
                ram+=vm2.getTotalRam();
                bw+=vm2.getTotalBw();
                disk+=vm2.getTotalDisk();
            }
            if(((vm.getTotalCpu()+cpu)<=this.getTotalCpu())&&((vm.getTotalRam()+ram)<=this.getTotalRam())
                    &&((vm.getTotalBw()+bw)<=this.getTotalBw())&&((vm.getTotalDisk()+disk)<=this.getTotalDisk())){
                return true;
            }
            return false;
        }
    }

    public boolean vmCreate(Vm vm) {
        // TODO Auto-generated method stub
        this.currentCpu = this.currentCpu + vm.getCurrentCpu();
        this.currentRam = this.currentRam + vm.getCurrentRam();
        this.currentBw = this.currentBw + vm.getCurrentBw();
        this.currentDisk = this.currentDisk + vm.getCurrentDisk();
        vmList.add(vm);
        vm.setHost(this);
        return true;
    }

    public void vmDestroy(Vm vm) {
        // TODO Auto-generated method stub
        this.currentCpu = this.currentCpu - vm.getCurrentCpu();
        this.currentRam = this.currentRam - vm.getCurrentRam();
        this.currentBw = this.currentBw - vm.getCurrentBw();
        this.currentDisk = this.currentDisk - vm.getCurrentDisk();
        vmList.remove(vm);
        vm.setHost(null);
    }

    public int getMigrationIn() {
        return migrationIn;
    }

    public void setMigrationIn(int migrationIn) {
        this.migrationIn = migrationIn;
    }

    public List<Double> getUtilizationHistory() {
        return utilizationHistory;
    }

    public void setUtilizationHistory(List<Double> utilizationHistory) {
        this.utilizationHistory = utilizationHistory;
    }

    public double getAdditionalPower() {
        return additionalPower;
    }

    public void setAdditionalPower(double additionalPower) {
        this.additionalPower = additionalPower;
    }

    public double additionalPower(Vm vm){
        return PowerModel.getPowerOfHostByCpuOR((double)vm.getCurrentCpu()/this.getTotalCpu(), (double)vm.getCurrentRam()/this.getTotalRam(),
                (double)vm.getCurrentBw()/this.getTotalBw(),(double)vm.getCurrentDisk()/this.getTotalDisk());
    }

    public double getScore() {
        return score;
    }

    public void setScore(double score) {
        this.score = score;
    }

    public int getLoadFlag() {
        return loadFlag;
    }

    public void setLoadFlag(int loadFlag) {
        this.loadFlag = loadFlag;
    }
}
